package com.ib.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ib.domain.DeviceValue;
import com.ib.domain.TypeData;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;

public abstract class CustomHeartbeatHandler extends ChannelInboundHandlerAdapter {

	private static final Logger LOG = LoggerFactory.getLogger(CustomHeartbeatHandler.class);

	protected String name;
	private int heartbeatCount = 0;
	
	private String ping = "Ping";
	private String pong = "Pong";

	public CustomHeartbeatHandler(String name) {
		this.name = name;
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		String deviceValue = (String) msg;
		LOG.info("CustomHeartbeatHandler type=" + deviceValue);
		if (ping.equals(deviceValue)){
			sendPong(ctx);
		}else if(pong.equals(deviceValue)) {
			LOG.info(name + " get pong msg from " + ctx.channel().remoteAddress());
		}else {
            handleData(ctx, msg);
		}
	}

	protected void sendPing(ChannelHandlerContext context) {
		context.channel().writeAndFlush(ping);
		heartbeatCount++;
		LOG.info(name + " sent ping msg to " + context.channel().remoteAddress() + ", count: " + heartbeatCount);
	}

	private void sendPong(ChannelHandlerContext context) {
		context.channel().writeAndFlush(pong);
		heartbeatCount++;
		LOG.info(name + " sent pong msg to " + context.channel().remoteAddress() + ", count: " + heartbeatCount);
	}

	protected abstract void handleData(ChannelHandlerContext channelHandlerContext, Object msg);

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		// IdleStateHandler 所产生的 IdleStateEvent 的处理逻辑.
		if (evt instanceof IdleStateEvent) {
			IdleStateEvent e = (IdleStateEvent) evt;
			switch (e.state()) {
			case READER_IDLE:
				handleReaderIdle(ctx);
				break;
			case WRITER_IDLE:
				handleWriterIdle(ctx);
				break;
			case ALL_IDLE:
				handleAllIdle(ctx);
				break;
			default:
				break;
			}
		}
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		LOG.info("---" + ctx.channel().remoteAddress() + " is active---");
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		LOG.info("---" + ctx.channel().remoteAddress() + " is inactive---");
	}

	protected void handleReaderIdle(ChannelHandlerContext ctx) {
		LOG.info("---READER_IDLE---");
	}

	protected void handleWriterIdle(ChannelHandlerContext ctx) {
		LOG.info("---WRITER_IDLE---");
	}

	protected void handleAllIdle(ChannelHandlerContext ctx) {
		LOG.info("---ALL_IDLE---");
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
        ctx.close();
	}
	
}
